package com.weilele.mvvm.view

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.*
import android.text.TextPaint
import android.util.AttributeSet
import com.weilele.mvvm.R
import com.weilele.mvvm.utils.activity.sp
import com.weilele.mvvm.widget.BaseView

open class ProgressTextView : BaseView {

    private val textPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).also {
        it.textAlign = Paint.Align.CENTER
    }
    private val bgPaint = Paint(Paint.ANTI_ALIAS_FLAG).also {
        it.color = Color.GREEN
        it.style = Paint.Style.FILL_AND_STROKE
    }

    /**
     * 检查是否允许重绘
     */
    private var enableInvalidate = true
    private fun checkInvalidate() {
        if (enableInvalidate) {
            invalidate()
        }
    }
    // 属性设置
    /**
     * 需要绘制的文字
     */
    var progressText: String? = null
        set(value) {
            field = value
            checkInvalidate()
        }

    /**
     * 文字大小
     */
    var normalTextSize: Float = 14f.sp
        set(value) {
            field = value
            checkInvalidate()
        }

    /**
     * 背景色
     */
    var bgColor: Int = 0
        set(value) {
            field = value
            checkInvalidate()
        }

    /**
     * 进度条颜色
     */
    var progressColor: Int = Color.GREEN
        set(value) {
            field = value
            checkInvalidate()
        }

    /**
     * 被进度条覆盖的文字颜色
     */
    var progressTextColor: Int = Color.WHITE
        set(value) {
            field = value
            checkInvalidate()
        }

    /**
     * 正常的文字颜色
     */
    var normalTextColor: Int = Color.BLACK
        set(value) {
            field = value
            checkInvalidate()
        }

    /**
     * 进度条和背景的圆角
     */
    var progressRadius: Float = 12f
        set(value) {
            field = value
            checkInvalidate()
        }

    /**
     * 进度条相对于背景的间距
     */
    var progressPadding = 0f
        set(value) {
            field = value
            checkInvalidate()
        }

    /**
     * 当前进度
     */
    var progress: Float = 0.5f
        set(value) {
            field = value
            checkInvalidate()
        }

    constructor(context: Context) : super(context)
    constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
        customAttributeSet(attrs)
    }


    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ) {
        customAttributeSet(attrs)
    }

    private fun customAttributeSet(attrs: AttributeSet?) {
        attrs ?: return
        enableInvalidate = false
        context.obtainStyledAttributes(attrs, R.styleable.ProgressTextView).apply {
            normalTextColor =
                getColor(R.styleable.ProgressTextView_normalTextColor, normalTextColor)
            progressTextColor =
                getColor(R.styleable.ProgressTextView_progressTextColor, progressTextColor)
            bgColor =
                getColor(R.styleable.ProgressTextView_bgColor, 0)
            progressColor =
                getColor(R.styleable.ProgressTextView_progressColor, progressColor)
            normalTextSize =
                getDimension(R.styleable.ProgressTextView_normalTextSize, normalTextSize)
            progressText =
                getString(R.styleable.ProgressTextView_progressText)
            progress =
                getFloat(R.styleable.ProgressTextView_progress, progress)
            progressPadding =
                getDimension(R.styleable.ProgressTextView_progressPadding, progressPadding)
            progressRadius =
                getDimension(R.styleable.ProgressTextView_progressRadius, progressRadius)
        }.recycle()
        enableInvalidate = true
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        canvas ?: return
        drawBg(canvas)
        drawProgress(canvas, false)
        canvas.saveLayer(null, null)
        drawText(canvas)
        drawProgress(canvas, true)
        canvas.restore()
    }

    /**
     *平滑的滚动进度条
     */
    private val anim by lazy {
        ValueAnimator.ofFloat().apply {
            addUpdateListener {
                val value = it.animatedValue as Float
                progress = value
            }
        }
    }

    /**
     *平滑的滚动进度条
     */
    fun smoothProgress(
        progress: Float,
        isSmooth: Boolean = true,
        duration: Long = 200L,
        text: String? = progressText
    ) {
        enableInvalidate = false
        progressText = text
        enableInvalidate = true
        if (duration <= 0 || !isSmooth) {
            this.progress = progress
        } else {
            if (anim.isRunning) {
                anim.cancel()
            }
            anim.setFloatValues(this.progress, progress)
            anim.duration = duration
            anim.start()
        }
    }

    /**
     * 设置进度和文本
     */
    fun setProgressAndText(progress: Float, text: String?) {
        enableInvalidate = false
        this.progress = progress
        enableInvalidate = true
        progressText = text
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val heightMode = MeasureSpec.getMode(heightMeasureSpec)
        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        val heightSize = MeasureSpec.getSize(heightMeasureSpec)
        if (widthMode == MeasureSpec.AT_MOST || heightMode == MeasureSpec.AT_MOST) {
            val text = progressText ?: ""
            setMeasuredDimension(
                if (widthMode == MeasureSpec.AT_MOST) {
                    (getTextPaint().measureText(text) + paddingStart + paddingEnd + progressPadding * 2).toInt()
                } else {
                    widthSize
                },
                if (heightMode == MeasureSpec.AT_MOST) {
                    getTextPaint().getFontMetrics(textFontMetrics)
//                    float height1 = fm.descent - fm.ascent;//文字高度
//                    float height2 = fm.bottom - fm.top + fm.leading;//行高
                    val textHeight = textFontMetrics.descent - textFontMetrics.ascent
                    (textHeight + paddingTop + paddingBottom + progressPadding * 2).toInt()
                } else heightSize
            )
        }
    }

    /**
     * 绘制背景
     */
    private fun drawBg(canvas: Canvas) {
        bgPaint.xfermode = null
        if (bgColor == 0) {
            return
        }
        bgPaint.color = bgColor
        canvas.drawRoundRect(
            getDrawRect(0f, 1f),
            progressRadius, progressRadius, bgPaint
        )
    }


    /**
     * 绘制进度
     */
    private fun drawProgress(canvas: Canvas, needXfermode: Boolean) {
        if (needXfermode) {
            bgPaint.color = progressTextColor
            bgPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        } else {
            bgPaint.color = progressColor
            bgPaint.xfermode = null
        }
        canvas.drawRoundRect(
            getDrawRect(progressPadding, progress),
            progressRadius,
            progressRadius,
            bgPaint
        )
    }

    /**
     * 绘制文字
     */
    private val textFontMetrics = Paint.FontMetrics()
    private fun drawText(canvas: Canvas) {
        val text = this.progressText
        if (text.isNullOrBlank()) {
            return
        }
        val textPaint = getTextPaint()
        val rect = getDrawRect(0f, 1f)
        val centerX = rect.centerX()
        val centerY = rect.centerY()
        textPaint.getFontMetrics(textFontMetrics)
        val offset: Float = (textFontMetrics.descent + textFontMetrics.ascent) / 2
        canvas.drawText(text, centerX, centerY - offset, textPaint)
    }

    private fun getTextPaint(): Paint {
        textPaint.color = normalTextColor
        textPaint.textSize = normalTextSize
        return textPaint
    }

    /**
     * 计算绘制的矩形
     */
    private val rect = RectF()
    private fun getDrawRect(progressPadding: Float, progress: Float): RectF {
        rect.set(
            paddingStart + progressPadding,
            paddingTop + progressPadding,
            (width - paddingStart - paddingEnd - progressPadding * 2) * progress + paddingStart + progressPadding,
            height - paddingBottom - progressPadding
        )
        return rect
    }
}